use sea_orm::{
    DatabaseConnection, DbErr, EntityTrait, QueryFilter, ColumnTrait,
    QuerySelect, ActiveValue::Set, sea_query::OnConflict
};
use crate::models::rbac::user_department::ActiveModel;
use crate::models::rbac::user_department::{Entity, Column};

pub struct UserDepartmentService;

impl UserDepartmentService {
    pub async fn assign_department_to_user(
        db: &DatabaseConnection,
        user_id: &str,
        department_id: &str,
        tenant_id: i64
    ) -> Result<u64, DbErr> {
        let mut model = ActiveModel {
            user_id: Set(user_id.to_string()),
            department_id: Set(department_id.to_string()),
            tenant_id: Set(Some(tenant_id)),
            ..Default::default()
        };

        Entity::insert(model)
            .on_conflict(
                OnConflict::columns([
                    Column::UserId,
                    Column::DepartmentId,
                    Column::TenantId
                ])
                .do_nothing()
                .to_owned()
            )
            .exec(db)
            .await
            .map(|_| 1)
    }

    pub async fn remove_department_from_user(
        db: &DatabaseConnection,
        user_id: &str,
        department_id: &str,
        tenant_id: i64
    ) -> Result<u64, DbErr> {
        Entity::delete_many()
            .filter(Column::UserId.eq(user_id))
            .filter(Column::DepartmentId.eq(department_id))
            .filter(Column::TenantId.eq(tenant_id))
            .exec(db)
            .await
            .map(|r| r.rows_affected)
    }

    pub async fn find_departments_by_user(
        db: &DatabaseConnection,
        user_id: &str,
        tenant_id: i64
    ) -> Result<Vec<String>, DbErr> {
        Entity::find()
            .filter(Column::UserId.eq(user_id))
            .filter(Column::TenantId.eq(tenant_id))
            .select_only()
            .column(Column::DepartmentId)
            .into_tuple()
            .all(db)
            .await
    }

    pub async fn find_users_by_department(
        db: &DatabaseConnection,
        department_id: &str,
        tenant_id: i64
    ) -> Result<Vec<String>, DbErr> {
        Entity::find()
            .filter(Column::DepartmentId.eq(department_id))
            .filter(Column::TenantId.eq(tenant_id))
            .select_only()
            .column(Column::UserId)
            .into_tuple()
            .all(db)
            .await
    }
}
